package com.kingstar.ceres.data.db;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.kingstar.ceres.data.constant.FileImportConstants;
import com.kingstar.ceres.data.db.entity.TaskLockEntity;
import com.kingstar.ceres.data.db.service.ITaskLockService;
import com.kingstar.ceres.data.handler.ITaskLockHandler;
import com.kingstar.ceres.data.util.FileImportUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

@Slf4j
public class TaskLockHandler implements ITaskLockHandler<TaskLockEntity> {

    private final ITaskLockService taskLockService;

    public TaskLockHandler(ITaskLockService taskLockService) {
        this.taskLockService = taskLockService;
    }

    public void resetTaskStatus(String taskId, List<String> fileIds,String opDate,String status){
        log.info("reset-task-status,taskId:{},fileIds:{},opDate:{},status:{}",taskId,fileIds,opDate,status);
        LambdaUpdateWrapper<TaskLockEntity> updateWrapper=new LambdaUpdateWrapper<>();
        updateWrapper.eq(TaskLockEntity::getTaskId,taskId);
        updateWrapper.eq(TaskLockEntity::getOpDate,opDate);
        updateWrapper.in(!CollectionUtils.isEmpty(fileIds),TaskLockEntity::getFileId,fileIds);
        updateWrapper.set(TaskLockEntity::getTaskStatus,status);
        taskLockService.update(updateWrapper);
    }

    public boolean taskSuccess(String taskId,String fileId,String opDate,String successStatus){
        log.info("before task-success;taskID:{},fileId:{},opDate:{}",taskId,fileId,opDate);
        LambdaQueryWrapper<TaskLockEntity> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(TaskLockEntity::getTaskId,taskId);
        wrapper.eq(TaskLockEntity::getOpDate,opDate);
        wrapper.eq(TaskLockEntity::getFileId,fileId);
        TaskLockEntity entity = taskLockService.getOne(wrapper);
        log.info("task-success;old entity:{}",entity);
        entity.ofComplete(successStatus);
        boolean flag = taskLockService.updateById(entity);
        return flag && FileImportUtils.taskSuccess(entity.getTaskStatus());
    }

    public boolean taskComplete(String taskId,String opDate){
        log.info("before task-complete;taskID:{},opDate:{}",taskId,opDate);
        LambdaQueryWrapper<TaskLockEntity> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(TaskLockEntity::getTaskId,taskId);
        wrapper.eq(TaskLockEntity::getOpDate,opDate);
        List<TaskLockEntity> list = taskLockService.list(wrapper);
        TaskLockEntity taskLockEntity=null;
        boolean flag=true;
        for (TaskLockEntity entity : list) {
            if (Objects.equals(taskId,entity.getFileId())){
                taskLockEntity=entity;
                continue;
            }
            if (Objects.equals(FileImportConstants.STATUS_FAILED,entity.getTaskStatus())){
                log.warn("文件入库执行失败:{}",entity);
                flag=false;
            }
        }
        if (taskLockEntity==null){
            log.warn("csv任务更新失败");
            return false;
        }

        if (flag){
            taskLockEntity.editStatus(FileImportConstants.STATUS_SUCCESS_CAN_RETRY,"执行成功");
            log.info("success task-complete;{}",taskLockEntity);
        }else {
            taskLockEntity.editStatus(FileImportConstants.STATUS_FAILED,"执行失败");
            log.warn("failed task-complete;{}",taskLockEntity);
        }
        taskLockService.updateById(taskLockEntity);
        return flag;
    }

    public void taskStatusChange(String taskId, String fileId, String opDate,String oldStatus ,String newStatus, String errMsg){
        log.info("task-status-change,taskId:{},fileId:{},opDate:{},oldStatus:{},newStatus:{},result:{}",
                taskId,fileId,opDate,oldStatus,newStatus,errMsg);
        LocalDateTime now = LocalDateTime.now();
        LambdaUpdateWrapper<TaskLockEntity> updateWrapper=new LambdaUpdateWrapper<>();
        updateWrapper.eq(TaskLockEntity::getTaskId,taskId);
        updateWrapper.eq(TaskLockEntity::getOpDate,opDate);
        updateWrapper.eq(TaskLockEntity::getFileId,fileId);
        updateWrapper.eq(StringUtils.isNotBlank(oldStatus),TaskLockEntity::getTaskStatus,oldStatus);
        updateWrapper.set(TaskLockEntity::getTaskStatus,newStatus);
        updateWrapper.set(TaskLockEntity::getErrorMsg,errMsg);
        updateWrapper.set(TaskLockEntity::getExecEndTime,now);
        updateWrapper.set(TaskLockEntity::getLastUpdatedTime,now);
        boolean update = taskLockService.update(updateWrapper);
        log.info("task-status-change result:{},taskId:{},fileId:{},opDate:{},oldStatus:{},newStatus:{},result:{}",
                update,taskId,fileId,opDate,oldStatus,newStatus,errMsg);
    }

    public boolean checkTaskStatusAndTransToDoing(String opDate, String taskID, String fileId,String execType){
        TaskLockEntity entity = selectAndInsertTask(opDate, taskID, fileId, execType);
        if (entity==null){
            log.info("查询条件不合规,opDate={},taskID={},fileId={}", opDate,taskID, fileId);
            return false;
        }
        if(!FileImportUtils.canDoTask(entity.getTaskStatus())){
            log.info("任务状态检查不通过,不可执行任务,entity={}",entity);
            return false;
        }
        LambdaUpdateWrapper<TaskLockEntity> wrapper=new LambdaUpdateWrapper();
        wrapper.eq(TaskLockEntity::getTaskId,taskID);
        wrapper.eq(TaskLockEntity::getOpDate,opDate);
        wrapper.eq(TaskLockEntity::getFileId,fileId);
        wrapper.in(TaskLockEntity::getTaskStatus, FileImportConstants.STATUS_CAN_DO);
        wrapper.set(TaskLockEntity::getTaskStatus,FileImportConstants.STATUS_DOING);
        wrapper.set(TaskLockEntity::getExecStartTime,LocalDateTime.now());
        wrapper.set(TaskLockEntity::getErrorMsg,"执行中");
        boolean update = taskLockService.update(wrapper);
        log.info("任务更新结果:{},opDate={},taskID={},fileId={}", update,opDate,taskID, fileId);
        return update;
    }

    public TaskLockEntity selectAndInsertTask(String opDate, String taskID, String fileId,String execType){
        if(StringUtils.isEmpty(opDate) || StringUtils.isEmpty(taskID) || StringUtils.isEmpty(fileId)){
            log.info("输入的查询条件,opDate={},taskID={},fileId={}", opDate,taskID, fileId);
            return null;
        }
        TaskLockEntity entity = queryTaskResultByID(taskID, opDate, fileId);
        //1.未执行则构建任务
        if(entity==null){
            // 构建未执行任务-0
            log.info("first create task,opDate={},taskID={},fileId={}", opDate,taskID, fileId);
            entity = insertNewTaskRecords(opDate, taskID, fileId,execType);
        }else {
            log.info("selectAndInsertTask result:{}",entity);
        }
        return entity;


    }

    public TaskLockEntity queryTaskResultByID(String taskId, String opDate, String fileId) {
        try {
            LambdaQueryWrapper<TaskLockEntity> wrapper=new LambdaQueryWrapper<>();
            wrapper.eq(TaskLockEntity::getTaskId,taskId);
            wrapper.eq(TaskLockEntity::getOpDate,opDate);
            wrapper.eq(TaskLockEntity::getFileId,fileId);
            List<TaskLockEntity> list = taskLockService.list(wrapper);
            if(list.size()>0){
                return list.get(0);
            }else {
                return null;
            }
        }catch (Exception e){
            log.error("查询 TASK_ID={},OP_DATE={},fileId={} 任务信息出错,{}",taskId,opDate,fileId,e);
            return null;
        }
    }

    public TaskLockEntity insertNewTaskRecords(String opDate, String taskID, String fileId,String execType) {
        try {
            TaskLockEntity entity = TaskLockEntity.ofCreate(opDate, taskID, fileId, execType);
            boolean save = taskLockService.save(entity);
            log.info("create new task success:TaskLockEntity={}",entity);
            if (save){
                return entity;
            }
            log.warn("create new task success insert failed,TaskLockEntity={}",entity);
            return null;
        }catch (Exception e){
            log.error("create new task failed:opDate={},taskID={},fileId={},execType={} 出错，{}",opDate,taskID,fileId,execType,e);
            return null;
        }
    }
}